package com.adwyxx.collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

/**
 * Java 集合可分为 {@link Collection}  和 {@link Map} 两大体系：
 * <pre>
 * - Collection 接口：用于存储一个一个的数据，也称单列数据集合。JDK不提供此接口的任何直接实现，而是提供更具体的子接口（Set和List）去实现。
 *  + List 子接口：用来存储有序的、可以重复的数据（主要用来替换数组，"动态"数组）
 *      * 实现类：ArrayList(主要实现类)、LinkedList、Vector
 *  + Set 子接口：用来存储无序的、不可重复的数据（类似于高中讲的"集合"）
 *      * 实现类：HashSet(主要实现类)、LinkedHashSet、TreeSet
 * - Map 接口：用于存储具有映射关系“key-value对”的集合，即一对一对的数据，也称双列数据集合。(类似于高中的函数、映射。(x1,y1),(x2,y2) ---> y = f(x) )
 *  + HashMap(主要实现类)、LinkedHashMap、TreeMap、Hashtable、Properties
 * </pre>
 *
 * @author Leo.W
 * @date 2024-09-12 9:32
 */
public class CollectionDemo {
    public static void main(String[] args) {
        testCollection();
    }

    /**
     * Collection 接口的通用方法：
     * 1.添加元素: add(E e) 和 addAll(Collection<? extends E> c)
     * 2.删除元素: remove(Object o) 、removeAll(Collection<?> c) 、removeIf(Predicate<? super E> filter)、clear() 和 retainAll(Collection<?> c)
     * 3.判断元素: contains(Object o) 和 containsAll(Collection<?> c)
     * 4.获取元素个数: size()
     * 5.判断是否为空: isEmpty()
     * 6.清空集合: clear()
     * 7.遍历集合: iterator()
     * 8.转换成数组: toArray()
     */
    private static void testCollection() {
        // Collection 接口对象： Collection -> List -> ArrayList
        Collection<Object> c = new ArrayList<>();
        c.add("a");
        c.add("b");
        c.add("c");

        Collection<String> other = new ArrayList<>();
        other.add("d");
        other.add("e");

        System.out.println("c -> " + c); // c -> [a, b, c]
        System.out.println("other -> " + other); // other -> [d, e]

        /*---------- add / addAll ----------*/
        // addAll(Collection other) 方法将 other 集合中的所有元素添加到 c 集合中
        c.addAll(other);
        System.out.println("c.addAll(other) -> " + c); // c.addAll(other) -> [a, b, c, d, e]

        // 注意: add() 和 addAll() 的区别:
        // addAll() 方法是将 other 集合中的所有元素添加到 c 集合中，而不是将 other 集合本身添加到 c 集合中
        c.add(other);
        System.out.println("c.add(other) -> " + c); // c.add(other) -> [a, b, c, d, e, [d, e]]

        /*---------- remove / removeIf / removeAll / retainAll / clear ----------*/
        // 从当前集合中删除第一个找到的与obj对象equals返回true的元素
        c.remove("e");
        System.out.println("c.remove(\"e\") -> " + c); // c.remove("e") -> [a, b, c, d, [d, e]]

        // removeIf(Predicate<? super E> filter) 方法用于删除满足 filter 条件的元素
        c.removeIf(e -> e.equals("a"));
        System.out.println("c.removeIf(e -> e.equals(\"a\")) -> " + c); // c.removeIf(e -> e.equals("a")) -> [b, c, d, [d, e]]

        // removeAll(Collection<?> c) 方法用于删除当前集合中包含在 c 集合中的所有元素
        c.removeAll(other); // 注意：c 中的 other 元素并不会删除，只删除了与 other中元素 相同的元素
        System.out.println("c.removeAll(other) -> " + c); // c.removeAll(other) -> [b, c,[d,e]]

        // retainAll(Collection<?> c) 从指定集合中保留包含集合c的元素,其他元素则删除
        c.retainAll(other);
        System.out.println("c.retainAll(other) -> " + c); // c.retainAll(other) -> []

        // clear() 方法用于清空当前集合中的所有元素
        c.clear();
        System.out.println("c.clear() -> " + c); // c.clear() -> []

        /*---------- contains / containsAll ----------*/
        c.add("X");
        c.add("Y");
        c.add("Z");
        // contains(Object o) 方法用于判断当前集合中是否包含指定元素，通过调用对象的 equals 方法判断
        // 注意：判断两个对象是否相等时候，需重写 hashCode 和 equals 方法
        System.out.println("c.contains(\"a\") -> " + c.contains("a")); // c.contains("a") -> false

        // containsAll(Collection<?> coll) 方法用于判断当前集合中是否包含 coll 集合中的所有元素，即 coll集合是否是当前集合的“子集”
        System.out.println("c.containsAll(other) -> " + c.containsAll(other)); // c.containsAll(other) -> false

        /*---------- isEmpty / size ----------*/
        // isEmpty() 方法用于判断当前集合是否为空
        System.out.println("c.isEmpty() -> " + c.isEmpty());

        // size() 方法用于返回当前集合中元素的个数
        System.out.println("c.size() -> " + c.size());

        // toArray() 方法用于将当前集合转换为数组
        Object[] arr = c.toArray();
        System.out.println("c.toArray() -> " + arr); // c.toArray() -> [Ljava.lang.Object;@2ed94a8b

        /*---------- iterator ----------*/
        c.add("XYZ");
        // iterator(): 获取集合对应的迭代器，用来遍历集合中的元素的。
        // 注意：
        // 在调用 it.next() 方法之前必须要调用 it.hasNext() 进行检测。
        // 若不调用，且下一条记录无效，直接调用 it.next() 会抛出 NoSuchElementException 异常。
        Iterator<Object> it = c.iterator();
        while (it.hasNext()) {
            Object obj = it.next();
            System.out.println("it.next() -> " + obj);
            // 迭代器的 remove() 可以按指定的条件进行删除
            if("XYZ".equals(obj)){
                // 注意：遍历过程中通过迭代器对象的 remove() 方法，不是集合对象的 remove() 方法。
                it.remove();
            }
        }
        System.out.println("c.iterator() -> it.remove() " + c); // c.iterator() -> [X, Y, Z]

        // foreach遍历
        c.forEach(e-> System.out.println(e));
        // 可以使用方法引用简写
        c.forEach(System.out::println);
        // 或者迭代器的forEachRemaining方法
        c.iterator().forEachRemaining(System.out::println);
    }

    /**
     * Map 接口方法：
     * <pre>
     * 9.获取集合中指定元素: get(Object key)
     * 10.判断集合中是否包含指定元素: containsKey(Object key)
     * 11.获取集合中所有键: keySet()
     * 12.获取集合中所有值: values()
     * 13.获取集合中所有键值对: entrySet()
     * </pre>
     */
    public static void testMap(){

    }
}
